/**
 * It's the prototype definition of the Footprint class.
 *
 */
var Footprint = Class.create();
Footprint.prototype = {
	map:null,				// To store the main map canvas.
	markersMgr:null,		// For future use of the Google Utility.
	
	mapTpl:'',				// To store the main map canvas html template.
	newMarker:null,			// A new marker.
	newMarkerFormTpl:'',	// To store the new marker creation form template.
	
	baseURL:'', 			// To store the footprint plugin root URL.
	markersURL:'', 			// To store the fetch markers php file URL.
	saveURL:'', 			// To store the save marker php file URL.
	
	existedMarkers:[], 		// To store the existed markers.
	currentMarker:null, 	// To store current actived marker.
	
	isLogin:null,
		

	/**
	 * Construction of the class Footprint
	 */
  	initialize: function(id,width,height,baseURL,isLogin) {
  		this.isLogin = isLogin;
    	this.id = id;
    	this.width = width;
    	this.height = height;
    	this.baseURL = baseURL;
    	this.markersURL = this.baseURL+"/markers.php";
    	this.saveURL = this.baseURL+"/save.php";
    	this.mapTpl = '<div id="'+this.id+'" style="width: '+this.width+'px; height: '+this.height+'px"></div>';
		this.mapTpl += '<div style="margin-top:10px;width:'+this.width+'px">';
		if (this.isLogin){
			this.mapTpl +='<button id="'+this.id+'NewMarkerBtn">New footprint</button>';
		}
		this.mapTpl += "</div>";
		this.newMarkerFormTpl = 'Place: <input id="'+this.id+'NewPlace" name="place" value="Dalian"><br><button id="'+this.id+'SaveBtn">Save</button>';
		this.createMap();
		this.getExistedMarkers();
	},	
	
	/**
	 * This method is used to create the main map canvas.
	 */
	createMap: function(){
		document.writeln(this.mapTpl);		
		if (this.isLogin){
			$(this.id+'NewMarkerBtn').onclick = this.onNewMarkerBtnClick.bind(this);
		}
		if (GBrowserIsCompatible()){
			this.map = new GMap2($(this.id),{draggableCursor:'auto',draggingCursor:'move'});
			var terr =new GMapType(G_PHYSICAL_MAP.getTileLayers(),G_PHYSICAL_MAP.getProjection(),"Relief");
  			this.map.addMapType(terr);
			this.map.addControl(new GSmallMapControl());
			this.map.addControl(new GMenuMapTypeControl());
			this.map.enableScrollWheelZoom();
			
			this.map.setCenter(new GLatLng(38.9616,121.6129), 4, terr);
			this.map.setMapType(G_HYBRID_MAP);
			
			GEvent.bind(this.map,"click",this,this.onMapClick);
		}		
	},
	
	/**
	 * This method is used to show the new marker creation form info window.
	 */
	showNewMarkerFormWindow: function(marker){
		marker.openInfoWindowHtml(this.makeNewMarkerFormHtml());
		GEvent.bind(marker,"infowindowopen",this,this.onNewMarkerFormWindowOpen);
	},
	
	/**
	 * This method is used to show the existed marker info window.
	 */
	showExistedMarkerInfoWindow: function(i){
		var marker = this.existedMarkers[i];
		var lat = marker.getLatLng().lat();
		var lng = marker.getLatLng().lng();
		new Ajax.Request(this.markersURL, {
			method: 'get',
			parameters: {
				'id': marker.id,
				'version': this.getVersionN()
			},
			onSuccess: this.onGetExistedMarkerSuccess.bind(this)
		});
	},
	
	makeInfoHtml: function(record){
		//alert(marker.getLatLng().lat().toFixed(5)+"---"+marker.getLatLng().lng().toFixed(2));
		var html = "<div style='width:300px;height:70px'>";
		html += "<B>"+record.place+"</b><BR>";
		html += record.lat+", "+record.lng+" | "+record.dt+"<BR>";
		html += record.cate;
		html += "<hr></div>";
		html += "<div style='overflow:auto;width:300px;height:160px'>";
		if (record.img_url){
			html += "<img src='"+record.img_url+"' align='right' width='160'>";
		}
		if (record.description){
			html += record.description;
		}else{
			html += "No description added yet.";
		}
		html += "</div>";
		
		return html;
	},
	
	makeNewMarkerFormHtml: function(){
		var html = "<div style='width:300px;height:250px'><p align='left'>";
		html += this.newMarker.getLatLng().lat().toFixed(7)+", "+this.newMarker.getLatLng().lng().toFixed(7)+"<br>";
		html += "Place: <input id='"+this.id+"NewPlace' name='place' value='' style='width:140px'> <input id='"+this.id+"Dt' name='dt' value='0000-00-00' style='width:80px'>";
		html += "<select style='width:90px' id='"+this.id+"Cate' name='cate'><option value='Home'>Home</option><option value='Birthplace'>Birghplace</option><option value='Study'>Study</option><option value='Work'>Work</option><option value='Tour' selected>Tour</option><option value='Other'>Other</option></select> ";
		html += "<input style='width:150px' type='text' id='"+this.id+"ImgUrl' name='img_url' value='Img URL'></P>";
		html += "<hr>";
		html += "<textarea style='overflow:auto;width:300px;height:130px;font-size:9pt' id='"+this.id+"Description' name='description'>";
		html += "</textarea><br><button id='"+this.id+"SaveBtn'>Save</button></div>";
		
		return html;
	},
	
	/**
	 * This method is used to close the info window of the map.
	 */
	closeInfoWindow: function(){		
		this.map.closeInfoWindow();		
	},
	
	/**
	 * This method is used to get the existed markers from server side.
	 */
	getExistedMarkers: function(){
		new Ajax.Request(this.markersURL, {
			method: 'get',
			parameters: {
      			'version': this.getVersionN()
      		},      		
      		onSuccess: this.onGetExistedMarkersSuccess.bind(this)
    	});
	},
	
	/**
	 * This method is used to generate a random version number.
	 */
	getVersionN: function(){
		return Math.round(Math.random()*100000000000);
	},
	
	/**
	 * Handler of get existed markers success event.
	 */
	onGetExistedMarkersSuccess: function(transport){
		var response = transport.responseText.evalJSON();
		for(var i=0;i<response.length;i++){
			var marker = new GMarker(new GLatLng(response[i].lat,response[i].lng),{draggable: false});
			marker.id = response[i].id;			
			this.map.addOverlay(marker);
			this.existedMarkers.push(marker);
		}      
	},
	
	/**
	 * Handler of getting existed marker success.
	 */
	onGetExistedMarkerSuccess: function(transport){
		var result = transport.responseText.evalJSON();
		if (result){
			//var marker = new GMarker(new GLatLng(result.lat,result.lng),{draggable: false});
			for(var i=0;i<this.existedMarkers.length;i++){
				if (this.existedMarkers[i].id==result.id){
					var info = this.makeInfoHtml(result);
					this.existedMarkers[i].openInfoWindowHtml(info);
					break;
				}
			}
		}
		//for(var i=0;i<response.length;i++){
		//	var marker = new GMarker(new GLatLng(response[i].lat,response[i].lng),{draggable: false});			
		//	this.map.addOverlay(marker);
		//	this.existedMarkers.push(marker);
		//}   
	},
	
	/**
	 * Handler of map click event.
	 */
	onMapClick: function(overlay, point){
		if (overlay){
			for(var i=0;i<this.existedMarkers.length;i++){
				// to process the existed markers click event.
				
				if (this.existedMarkers[i]==overlay){
					// to find which marker user cliced and show the info window upon it.
					this.showExistedMarkerInfoWindow(i);
					return;
				}  
			}
			if (overlay==this.newMarker){
				// to process the new created marker click event.
				this.showNewMarkerFormWindow(overlay);
				return;
			}
			if (overlay==this.currentMarker){
				// todo...
				return;
			}
		}
	},
	
	/**
	 * Handler of new create marker form window, to bind an event handler to save button.
	 */
	onNewMarkerFormWindowOpen: function(){
		$(this.id+'SaveBtn').onclick = this.onSaveBtnClick.bind(this);
	},
	
	/**
	 * Handler of save button clicked. To send the Ajax request to server side to save the new marker.
	 */
	onSaveBtnClick: function(){
		var img_url = '';
		if ($(this.id+'ImgUrl').value=="Img URL"){
			img_url = '';
		}else{
			img_url = $(this.id+'ImgUrl').value;
		}
		new Ajax.Request(this.saveURL, {
			method: 'get',
			parameters: {
				'lat': this.newMarker.getLatLng().lat().toFixed(7),
				'lng': this.newMarker.getLatLng().lng().toFixed(7),
				'place': $(this.id+'NewPlace').value,
				'cate': $(this.id+'Cate').value,
				'dt': $(this.id+'Dt').value,
				'img_url': img_url,
				'description': $(this.id+'Description').value,
				'version': this.getVersionN()
			},
			onSuccess: this.onSaveSuccess.bind(this)
		});
	},
	
	/**
	 * Handler of saving success.
	 */
	onSaveSuccess: function(transport){
		this.closeInfoWindow();
		if (transport.responseText!=null){
			var response = transport.responseText.evalJSON();
			if (response!=null){
				if (this.newMarker!=null){
					this.map.removeOverlay(this.newMarker);
					this.newMarker = null;
				}
				var marker = new GMarker(new GLatLng(response.lat,response.lng),{draggable: false});
				marker.id = response.id;			
				this.map.addOverlay(marker);
				this.existedMarkers.push(marker);
				this.map.setCenter(marker.getLatLng());
			}
		}
		
	},
	
	/**
	 * Handler of new marker button clicked.
	 */
	onNewMarkerBtnClick: function(){
		if (this.newMarker!=null){
			this.map.removeOverlay(this.newMarker);
		}
		
		this.newMarker = new GMarker(this.map.getCenter(),{draggable: true});
		GEvent.bind(this.newMarker,"dragstart",this,this.onMarkerDragStart);
		//GEvent.bind(this.newMarker,"drag",this,this.onMarkerDrag);
		GEvent.bind(this.newMarker,"dragend",this,this.onMarkerDragEnd);
		this.map.addOverlay(this.newMarker);
		this.showNewMarkerFormWindow(this.newMarker);
	},
	
	/**
	 * Handler of marker dragging start.
	 */
	onMarkerDragStart: function(){
		this.closeInfoWindow();
	},
	
	/**
	 * Handler of marker dragging.
	 */
	onMarkerDrag: function(latlng){
		//$(this.id+'_lat').value = latlng.lat();
		//$(this.id+'_lng').value = latlng.lng();
	},
	
	/**
	 * Handler of marker dragging end.
	 */
	onMarkerDragEnd: function(){
		this.showNewMarkerFormWindow(this.newMarker);
	}
}